import 'dart:convert';

import 'package:xindong/common/xindong_api_path.dart';
import 'package:xindong/common/xindong_define.dart';
import 'package:xindong/common/xindong_all.dart';
import 'package:xindong/common/xindong_methods.dart';
import 'package:xindong/common/xindong_storage.dart';
import 'package:xindong/common/xindong_types.dart';
import 'package:xindong/manager/network/xindong_networking.dart';
import 'package:xindong/manager/xindong_chat_singleton.dart';
import 'package:xindong/manager/xindong_gift_animation_ctr.dart';
import 'package:xindong/manager/xindong_page_singleton.dart';
import 'package:xindong/manager/xindong_user_controller.dart';
import 'package:xindong/manager/xindong_shengyin_zhendong_singleton.dart';
import 'package:xindong/models/chat_message/xindong_custom_gift_message.dart';
import 'package:xindong/models/chat_message/xindong_custom_message.dart';
import 'package:xindong/models/gift/xindong_gift_chat_class.dart';
import 'package:xindong/models/user/xindong_base_user.dart';
import 'package:xindong/models/user/xindong_user.dart';
import 'package:xindong/routes/call/controller/xindong_call_controller.dart';
import 'package:xindong/routes/call/controller/xindong_call_timer_ctr.dart';
import 'package:xindong/routes/conversation/input/xindong_liaotian_input_controller.dart';
import 'package:xindong/routes/tab_chats/controller/xindong_liaotian_vm.dart';
import 'package:xindong/utils/xindong_conversion_util.dart';
import 'package:xindong/utils/xindong_text_util.dart';
import 'package:xindong/utils/queue/xindong_svga_queue.dart';
import 'package:xindong/widgets/dialog/xindong_alert_message.dart';
import 'package:xindong/widgets/floating_screen/xindong_piao_ping_singleton.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/separate_models/tui_chat_separate_view_model.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/message.dart';

class XinDongTencentSingleton {
  String customerID = ""; // 客服

  // 系统消息
  static const String IM_SYSTEM = "notice_admin";
  static const String IM_ADMIN = "administrator";
  static const String IM_GIFT_ROOM = "GiftChatRoom";

  // 是不是客服号
  bool isServer(XinDongBaseUser user) {
    return user.uid == customerID;
  }

  // 是不是邀请信令
  bool isInvitationSignaling(V2TimMessage message) {
    if (message.elemType != MessageElemType.V2TIM_ELEM_TYPE_CUSTOM) return false;

    if (message.customElem?.data == null) return false;

    final String data = message.customElem!.data!;
    if (data.contains("inviteID") && data.contains("inviter") && data.contains("actionType")) {
      return true;
    } else {
      return false;
    }
  }

  // other
  late final CoreServicesImpl coreServicesImpl = TIMUIKitCore.getInstance();

  late bool isAddListener = false;

  // 初始化监听
  Future<void> setup() async {
    // 客服
    customerID = XinDongStorage.instance.getString(XinDongStorageKey.kefu) ?? "";
    // 反初始化
    await coreServicesImpl.unInit();
    bool? result = await coreServicesImpl.init(
      sdkAppID: XinDongAll.instance.isRelease ? kTencentAppID : kTencentAppIDDebug,
      loglevel: XinDongAll.instance.isRelease ? LogLevelEnum.V2TIM_NULL : LogLevelEnum.V2TIM_LOG_DEBUG,
      listener: V2TimSDKListener(
        onKickedOffline: () {
          XinDongUserController.to.passiveLogout(showTips: "您被踢下线了\n该账号在另一台设备登录");
        },
        onUserSigExpired: () {
          XinDongUserController.to.passiveLogout(showTips: "您的账号签名已失效\n请重新登录");
        },
        onConnectFailed: (code, error) {
          mDebugPrint("$code $error");
        },
      ),
    );
    mDebugPrint("TencentImSDK init $result");
    // 登录
    login();
    // 一定要返回
    return Future.value();
  }

  // 获取客服号
  void getCustomer() async {
    final object = await XinDongNetworking.instance.request(XinDongApi.getCustomer);
    if (object.code == XinDongServerStatus.success) {
      customerID = object.msg;
      XinDongStorage.instance.saveString(XinDongStorageKey.kefu, customerID);
    } else {
      await Future.delayed(const Duration(seconds: 5));
      return getCustomer();
    }
  }

  // MARK: -
  // 登录
  Future<void> login() async {
    if (!XinDongUserController.to.isUserCompleted) {
      return;
    }
    // IM监听
    addListener();

    final userId = "${XinDongUserController.to.loginId}";
    V2TimCallback result = await coreServicesImpl.login(
      userID: userId,
      userSig: "${XinDongUserController.to.loginSig}",
    );
    if (result.code == 0) {
      mDebugPrint(" 🍏IM登录成功");
      XinDongLiaoTianVM.to.loginUserId = userId;
      Future.delayed(Duration.zero).whenComplete(() {
        XinDongLiaoTianVM.to.refreshData();
        XinDongLiaoTianVM.to.loadData();
        // 推送设置
        // XinDongPushSingleton.instance.initAfterChatLogin();
        // this.setOfflinePush();
      });
      Future.delayed(const Duration(seconds: 1)).whenComplete(() {
        enterGiftRoom();
        // XinDongBlackListController.to.loadData();
        // XinDongEverydayReset.instance.detection();
      });
      return Future.value();
    } else if (result.code == 70014) {
      showToast("SDKAppID does not match the Usersig.");
      XinDongUserController.to.passiveLogout();
      return Future.value();
    } else {
      mDebugPrint('🍎IM登录失败，5秒后尝试重新登录  ${result.desc}');
      // 失败，5秒后继续请求，直至成功
      await Future.delayed(const Duration(seconds: 5));
      return await login();
    }
  }

  // 登出
  void logout() async {
    exitGiftRoom();
    V2TimCallback result = await coreServicesImpl.logout();
    if (result.code == 0) {
      try {
        // 清除数据和监听
        // 去掉provider里面的所有东西
        // XinDongBlackListController.to.clear();
      } catch (e) {
        mCatchPrint(e);
      }
    }
  }

  // 添加监听，自定义消息
  // 注意只能添加一次，也不能移除监听，不然会移除TIMUIKitCore里面的
  void addListener() {
    if (isAddListener) {
      return;
    }
    isAddListener = true;
    // 注册高级消息监听器
    TencentImSDKPlugin.v2TIMManager.getMessageManager().addAdvancedMsgListener(
          listener: V2TimAdvancedMsgListener(
            // MARK: 已读回执
            onRecvC2CReadReceipt: (List<V2TimMessageReceipt> receiptList) {},

            // MARK: 撤回消息
            onRecvMessageRevoked: (String msgID) {
              // 会话列表显示消息撤回
              List<XinDongLiaoTianClass> conversationList = XinDongLiaoTianVM.to.conversationList;
              for (XinDongLiaoTianClass model in conversationList) {
                if (model.conversation.lastMessage?.msgID == msgID) {
                  model.conversation.lastMessage?.status = MessageStatus.V2TIM_MSG_STATUS_LOCAL_REVOKED;
                  XinDongLiaoTianVM.to.update();
                  break;
                }
              }
            },

            // MARK: 收到新消息
            onRecvNewMessage: (V2TimMessage message) async {
              try {
                // 信令消息
                if (isInvitationSignaling(message)) {
                  return;
                }
                if (message.groupID == null) {
                  // 如果是IM_ADMIN发的自定义消息，就要另外处理
                  if (message.sender == IM_ADMIN) {
                    // if (decode.contains('code') && decode.contains('action')) {
                    //   final map = XinDongConversionTool.decodeUnicodeJsonToMap(decode);
                    //   XinDongSignalCallClass model = XinDongSignalCallClass.fromJson(map);
                    //   if (model.action == "Home/Privatechat/toRequest") {
                    //     XinDongCallController.to.onReceiveCall(model: model, message: message);
                    //   } else if (model.action == "Home/Privatechat/returnRequest") {
                    //     XinDongCallController.to.onReceiveCallStatus(model: model, message: message);
                    //   }
                    // }
                    // this.dealWithAdminMessage(message.customElem?.data, message);
                  } else {
                    final decode = message.customElem?.data ?? "";
                    if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_CUSTOM) {
                      XinDongCustomMessage? model = XinDongConversionUtil.decodeJsonToMessageClass(decode);
                      if (model != null && model.type != null) {
                        final type = int.parse('${model.type}');
                        switch (type) {
                          // case ChatType.callAudio:
                          // case ChatType.callVideo:
                          //   {
                          //     print("objectmmmm 111");
                          //     if (model.content == null) break;
                          //     print("objectmmmm 222");
                          //     final signal = XinDongSignalClass.fromJson(model.content);
                          //     print("objectmmmm 333");
                          //     final callType =
                          //         type == ChatType.callAudio ? XinDongCallType.audioCall : XinDongCallType.videoCall;
                          //     XinDongCallController.to
                          //         .onReceiveInvitation(callType: callType, model: signal, message: message);
                          //   }
                          //   break;
                          case ChatType.gift:
                            {
                              final gift = XinDongGiftChatClass.fromJson(model.data!);
                              XinDongGiftAnimationCtr.to.addQueue(SVGAClass(
                                type: SVGAType.receiveGift,
                                name: gift.name,
                                svga: gift.cover_svga ?? "",
                              ));
                            }
                            break;
                          case ChatType.poor:
                            {
                              XinDongCallTimerController.to.showBalanceView(15);// model.second
                            }
                            break;
                        }
                      }
                    }

                    // 震动声音
                    XinDongShengYinZhenDongSingleton.instance.playVoiceAndVibrate();
                    // 触发亲密度刷新
                    XinDongChatSingleton.instance.countTrigger(message.sender ?? "");
                  }
                } else {
                  // Provider.of<XinDongTalkVideoProvider>(navigatorKey.currentContext!, listen: false).onReceiveNewGroupMessage(message);
                  onReceiveNewGroupMessage_giftRoom(message);
                  // // XinDongRoomProvider.instance.onReceiveNewGroupMessage(message);
                }
              } catch (e) {
                mCatchPrint(e);
              }
            },

            // MARK: 消息进度
            onSendMessageProgress: (V2TimMessage message, int progress) {},
          ),
        );
    // 注册信令消息监听器
    TencentImSDKPlugin.v2TIMManager.getSignalingManager().addSignalingListener(
          listener: V2TimSignalingListener(
            // MARK: 接收到新邀请
            onReceiveNewInvitation: XinDongCallController.to.onReceiveNewInvitation,

            // MARK: 接受邀请
            onInviteeAccepted: XinDongCallController.to.onInviteeAccepted,

            // MARK: 拒绝邀请
            onInviteeRejected: XinDongCallController.to.onInviteeRejected,

            // MARK: 取消邀请
            onInvitationCancelled: XinDongCallController.to.onInvitationCancelled,

            // MARK: 邀请超时
            onInvitationTimeout: XinDongCallController.to.onInvitationTimeout,
          ),
        );
    //注册会话监听器
    TencentImSDKPlugin.v2TIMManager.getConversationManager().setConversationListener(
          listener: V2TimConversationListener(
            // MARK: 新的会话
            onNewConversation: (List<V2TimConversation> conversationList) {
              try {
                XinDongLiaoTianVM.to.updateConversationList(conversationList);
              } catch (e) {
                mCatchPrint(e);
              }
            },

            // MARK: 会话更新
            onConversationChanged: (List<V2TimConversation> conversationList) {
              try {
                XinDongLiaoTianVM.to.updateConversationList(conversationList);
              } catch (e) {
                mCatchPrint(e);
              }
            },
            onSyncServerFailed: () {},
            onSyncServerFinish: () {},
            onSyncServerStart: () {},
          ),
        );
    TencentImSDKPlugin.v2TIMManager.getFriendshipManager().setFriendListener(listener: V2TimFriendshipListener(
      onFriendListDeleted: (friendInfo) => XinDongLiaoTianVM.to.deleteConversationFriendInfo(friendInfo),
      onFriendListAdded: (friendInfo) => XinDongLiaoTianVM.to.updateConversationFriendInfo(friendInfo),
      onFriendInfoChanged: (friendInfo) => XinDongLiaoTianVM.to.updateConversationFriendInfo(friendInfo),
    ));
  }

  // 腾讯云服务器时间（秒）
  Future<int?> serverSeconds() async {
    V2TimValueCallback<int> server = await TencentImSDKPlugin.v2TIMManager.getServerTime();
    return server.data;
  }

  Future<bool> sendCustomMessage({
    required String userId,
    required String groupID,
    required TUIChatSeparateViewModel chatSeparateVM,
    required Map data,
  }) async {
    // Map转Json字符串
    String jsonString = json.encode(data);
    //customElem={extension=, data={"type":0,"content":"看着离的很近，可以一起坐坐吗？","score":0}, nextElem={}, desc=},
    //customElem={extension=, data={"type":0,"content":"发","score":3.8}, nextElem={}, desc=}
    V2TimValueCallback<V2TimMessage>? result;
    if (!TextUtil.isEmpty(userId)) {
      result = await MessageUtils.handleMessageError(
        chatSeparateVM.sendCustomMessage(data: jsonString, convID: userId, convType: ConvType.c2c),
        navigatorKey.currentContext!,
      );
    } else if (!TextUtil.isEmpty(groupID)) {
      // 创建消息对象
      V2TimValueCallback<V2TimMsgCreateInfoResult> createMessage =
          await TencentImSDKPlugin.v2TIMManager.getMessageManager().createCustomMessage(data: jsonString);
      if (createMessage.code != 0) {
        return false;
      }
      result = await TencentImSDKPlugin.v2TIMManager.getMessageManager().sendMessage(
            id: createMessage.data!.id!, // 将消息创建id传递给
            receiver: "", // 用户ID，不是C2C传空字符串
            groupID: groupID, // 群ID，不是Group传空字符串
            priority: MessagePriorityEnum.V2TIM_PRIORITY_LOW,
          );
    }
    return result != null;
  }

  // ======== 单例
  // 工厂方法构造函数
  factory XinDongTencentSingleton() => _getInstance();

  // instance的getter方法，singletonManager.instance获取对象
  static XinDongTencentSingleton get instance => _getInstance();

  // 静态变量_instance，存储唯一对象
  static XinDongTencentSingleton? _instance;

  // 获取对象
  static XinDongTencentSingleton _getInstance() {
    _instance ??= XinDongTencentSingleton._internal();
    return _instance!;
  }

  // 私有的自定义命名式构造方法，通过它实现一个类;
  // 子类不能继承internal
  // 不是关键字，可定义其他名字
  XinDongTencentSingleton._internal() {
    //初始化(设置一些默认的)...
  }
}

/// 群聊
extension XinDongTencentGroup on XinDongTencentSingleton {
  // 加入聊天室
  void joinGroupChatRoom({required String groupID, required bool isOwner}) async {
    // 未登录
    if (!XinDongUserController.to.isUserCompleted) {
      mDebugPrint("未登录");
      return;
    }
    // 房主
    if (isOwner) {
      // 按照TRTC的demo，先走创建聊天室
      V2TimValueCallback result = await TencentImSDKPlugin.v2TIMManager.getGroupManager().createGroup(
            groupType: "AVChatRoom", // 聊天室
            groupID: groupID, // ID
            groupName: groupID, // 编号（暂用房间ID）
            addOpt: GroupAddOptTypeEnum.V2TIM_GROUP_ADD_ANY, // 任何人都可以加入
          );
      int code = result.code;
      if (code == 0) {
        mDebugPrint("聊天室创建成功，只要不被删除，历史上就只会调用一次");
      } else if (code == 10036) {
        mDebugPrint(
            "聊天室未开通音视频聊天室功能，创建聊天室数量超过限额，请前往腾讯云官网开通【IM音视频聊天室】，地址：https://cloud.tencent.com/document/product/269/11673");
      } else if (code == 10037) {
        mDebugPrint("聊天室单个用户可创建和加入的群组数量超过了限制，请购买相关套餐,价格地址：https://cloud.tencent.com/document/product/269/11673");
      } else if (code == 10038) {
        mDebugPrint("聊天室群成员数量超过限制，请参考，请购买相关套餐，价格地址：https://cloud.tencent.com/document/product/269/11673");
      } else if (code == 10025 || code == 10021) {
        // 10025 表明群主是自己，那么认为创建房间成功
        // 群组 ID 已被其他人使用，此时走进房逻辑
        V2TimCallback joinResult =
            await TencentImSDKPlugin.v2TIMManager.joinGroup(groupID: groupID.toString(), message: "");
        if (joinResult.code == 0 || joinResult.code == 10013) {
          mDebugPrint("聊天室加入成功 $groupID");
        } else {
          /// 进入房间失败，5秒后继续重新进入，直至成功
          Future.delayed(const Duration(seconds: 5), () {
            joinGroupChatRoom(groupID: groupID, isOwner: isOwner);
          });
        }
      }
    } else {
      V2TimCallback joinResult =
          await TencentImSDKPlugin.v2TIMManager.joinGroup(groupID: groupID.toString(), message: "");
      if (joinResult.code == 0 || joinResult.code == 10013) {
        mDebugPrint("聊天室加入成功，或者已经是群成员$groupID");
      } else if (joinResult.code == 10015) {
        mDebugPrint("聊天室无效房间ID，可以尝试创建一个");
        Future.delayed(const Duration(seconds: 5), () {
          joinGroupChatRoom(groupID: groupID, isOwner: true);
        });
      } else {
        mDebugPrint("加入失败 ${joinResult.code} ${joinResult.desc}");

        /// 进入房间失败，5秒后继续重新进入，直至成功
        Future.delayed(const Duration(seconds: 5), () {
          joinGroupChatRoom(groupID: groupID, isOwner: isOwner);
        });
      }
    }
  }

  /// 退出聊天室
  Future quitGroup({required String groupID, required bool isOwner}) async {
    if (isOwner) {
      // V2TimCallback result = await TencentImSDKPlugin.v2TIMManager.dismissGroup(groupID: roomId.toString());
      // XinDongDebugPrint("聊天室解散 ${result.code} ${result.desc}");
    } else {
      V2TimCallback result = await TencentImSDKPlugin.v2TIMManager.quitGroup(groupID: groupID);
      mDebugPrint("聊天室退出 ${result.code} ${result.desc}");
    }
    return Future.value();
  }
}

extension XinDongTencentChatRoom on XinDongTencentSingleton {
  void enterGiftRoom() {
    joinGroupChatRoom(groupID: XinDongTencentSingleton.IM_GIFT_ROOM, isOwner: false);
  }

  void exitGiftRoom() async {
    quitGroup(groupID: XinDongTencentSingleton.IM_GIFT_ROOM, isOwner: false);
  }

  // 回调 - 接收自定义群组消息
  void onReceiveNewGroupMessage_giftRoom(V2TimMessage message) {
    // 不是当前房间的消息不处理
    if (message.groupID != XinDongTencentSingleton.IM_GIFT_ROOM) {
      return;
    }
    if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_CUSTOM && message.customElem != null) {
      try {
        Map<String, dynamic> data = json.decode(message.customElem!.data!);
        XinDongCustomMessage? model = XinDongCustomMessage.fromJson(data);
        mDebugPrint('收到群组消息==== ${model.toJson()}');
        if (model.type != null) {
          final type = int.parse('${model.type}');
          switch (type) {
            case ChatType.gift: //礼物
              {
                final giftMessage = XinDongCustomGiftMessage.fromJson(data);
                XinDongPiaoPingSingleton.instance.addQueue(giftMessage);
              }
              break;
          }
        }
      } catch (e) {
        mCatchPrint(e);
      }
    }
  }
}

extension SendMessageResult on XinDongTencentSingleton {
// 发送失败
// 若业务希望拒绝发言的同时，将错误码 ErrorCode 和 ErrorInfo 传递至客户端，请将错误码 ErrorCode 设置在 [120001, 130000] 区间内
  Future<void> errorCode(V2TimValueCallback result, XinDongUser? userClass) async {
    if (result.code == 0) {
      if (userClass != null) {
        // 成功，如果对方是主播，则扣费
        // if (userClass.isAnchor == true) {
        //   XinDongUserSingleton.instance
        //       .decrementCoins(XinDongGlobal.instance.configurationClass.chatPrice ?? 0.5, needRequest: false);
        // }
        // 触发亲密度刷新
        XinDongChatSingleton.instance.countTrigger(userClass.uid);
      }
    } else if (result.code == 6013) {
      showToast("SDK未初始化，请重新启动应用");
    } else if (result.code == 6014) {
      showToast("IM未登录，请重新启动应用");
    } else if (result.code == 6017) {
      showToast("${result.code}对方IM账户异常，请反馈给客服。");
    } else if (result.code == 10016 || result.code == 20006) {
      showToast("内容违规");
    } else if (result.code == 20007) {
      XinDongLiaoTianInputController.to.inputController.clear();
      showToast("您已被对方拉入黑名单");
    } else if (result.code == 20016) {
      showToast("${result.code}消息撤回超过了时间限制");
    } else if (result.code == 60018 || result.code == 60019) {
      showToast("${result.code}请求过于频繁，请稍后重试。");
    } else if (result.code == 80001) {
      showToast("${result.code}文本存在敏感内容，禁止下发。");
    } else if (result.code == 80003) {
      showToast("${result.code}回调失败或回包超时，请反馈给客服。");
    } else if (result.code == 80004) {
      showToast("${result.code}图片存在敏感内容，禁止下发。");
    } else if (result.code > 120001 && result.code <= 130000) {
      // 120007  你已进入对方黑名单，无法发送消息
      // 120020  需要真人认证跟实名认证后可畅聊无阻
      // 120021  请和异性发消息吧
      // 120005  当前账号已被冻结
      // 120025  这个是市场审核员的  （一般女用户发不了消息给他的，看看你那边怎么处理）
      // 120026  内容存在违规内容,请重新编辑!
      // 120031  余额不足，立即充值！
      switch (result.code) {
        case 120020:
          {
            XinDongAlertMessage.show(
              content: result.desc,
              button: "去认证",
              onTapButton: () {
                XinDongPageSingleton.instance.toAuthYeMian();
              },
            );
          }
          break;
        case 120031:
          {
            XinDongAlertMessage.show(
              content: result.desc,
              button: "立即充值",
              onTapButton: () {
                XinDongPageSingleton.instance.toRechargeYeMian();
              },
            );
          }
          break;
        default:
          showToast(result.desc);
          break;
      }
    } else {
      showToast("发送失败，重启应用或者联系客服\n${result.code} ${result.desc}"); //发送失败
    }
    return Future.value();
  }
}
